package com.om39a.plm.service;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.log4j.Logger;

import com.om39a.plm.crawler.BrowseLoginPage;
import com.om39a.plm.crawler.DefaultBrowser;
import com.om39a.plm.crawler.PLMBrowser;
import com.om39a.plm.exceptions.NoNextPageException;
import com.om39a.plm.exceptions.PageLoadFailedException;
import com.om39a.plm.parser.PLMUserCondition;
import com.om39a.plm.parser.PLMThreadPost;
import com.om39a.plm.parser.PLMUser;
import com.om39a.plm.parser.ParserForumUrl;
import com.om39a.plm.parser.ParserUserProfilePage;
import com.om39a.plm.parser.ParserThreadUrl;
import com.om39a.plm.utils.PLMConstants;
import com.om39a.plm.utils.PLMFileUtils;
import com.om39a.plm.utils.PLMUtils;
import com.om39a.plm.utils.PLMXlsUtils;

/**
 * @author om39a
 * 
 */
public class PLMService {

	private static PLMService plmService = new PLMService();
	private static Logger logger = Logger.getLogger(PLMService.class);

	private PLMService() {

	}

	public static PLMService getInstance() {
		return plmService;
	}

	/**
	 * Step 1 - Login
	 * 
	 * @param args
	 * @return TODO
	 */
	public boolean login(Map<String, String> args) {
		logger.info("=====================");
		logger.info("Entring in to login - " + args);
		boolean isLoginSuccess = true;
		PLMBrowser browser = new BrowseLoginPage();
		String content = null;
		try {
			content = browser.execute(
					PLMUtils.appendBaseURL(PLMConstants.URL_LOGIN_PAGE), args);
			if (content.contains("Login unsuccessful")) {
				isLoginSuccess = false;
				logger.info("Login Failed");
			}
		} catch (PageLoadFailedException e) {
			isLoginSuccess = false;
			e.printStackTrace();
			logger.info(e);
		} catch (Exception e) {
			isLoginSuccess = false;
			e.printStackTrace();
			logger.info(e);
		}
		logger.info("Entring in to login ");
		logger.info("=====================");
		return isLoginSuccess;
	}

	/**
	 * Step 2 - using the forum url, collect the url list of the threads in the
	 * the forum to a text file
	 * 
	 * @param args
	 * @throws PageLoadFailedException
	 */
	public void grabThreadUrls(Map<String, String> args)
			throws PageLoadFailedException {
		logger.info("=====================");
		logger.info("Entring in to grabThreadUrls - " + args);
		
		PLMBrowser browser = new DefaultBrowser();
		ParserForumUrl parser = new ParserForumUrl();
		String nextPageUrl = null;

		String threadUrlOutputFile = args
				.get(PLMConstants.THREAD_URL_OUTPUT_FILE) == null
				|| "".equals(args.get(PLMConstants.THREAD_URL_OUTPUT_FILE)) ? "step1.txt"
				: args.get(PLMConstants.THREAD_URL_OUTPUT_FILE);

		String minReplies = args.get(PLMConstants.MIN_REPLIES) == null
				|| "".equals(args.get(PLMConstants.MIN_REPLIES)) ? "10" : args
				.get(PLMConstants.MIN_REPLIES);

		logger.info("Loading url " + args.get(PLMConstants.FORUM_URL));
		String mainForumContent = browser.execute(args
				.get(PLMConstants.FORUM_URL));
		List<String> forumTopicURLs = new ArrayList<String>();
		parser.parse(mainForumContent, Integer.valueOf(minReplies),
				forumTopicURLs);
		while (true) {
			// to Break loop when max number of threads reached
			try {
				nextPageUrl = parser.nextPage(mainForumContent);
				logger.info("Next page url " + nextPageUrl);
				if (null == nextPageUrl || "".equals(nextPageUrl)) {
					break;
				} else if (nextPageUrl.equalsIgnoreCase(args
						.get(PLMConstants.END_PAGE_URL))) {
					return;
				}
			} catch (NoNextPageException e) {
				e.printStackTrace();
				logger.info(e);
				break;
			} catch (Exception e) {
				e.printStackTrace();
				logger.info(e);
			}
			mainForumContent = browser.execute(nextPageUrl);
			// We have list of threads in which we need to brows through and get
			// the
			// thread contents
		}
		logger.info("Crawling thread url list completed");
		logger.info("Thread Url List - " + forumTopicURLs);

		// Writing thread topics to text file
		PLMFileUtils plmFileUtils;
		try {
			plmFileUtils = new PLMFileUtils(threadUrlOutputFile);
			StringBuffer buffer = new StringBuffer();
			for (Object object : forumTopicURLs) {
				buffer.append((String) object);
				buffer.append("\n");
			}
			plmFileUtils.writeToFile(buffer.toString());
		} catch (IOException e) {
			e.printStackTrace();
			logger.info(e);
		} catch (Exception e) {
			e.printStackTrace();
			logger.info(e);
		}
		logger.info("Exiting grabThreadUrls");
		logger.info("=====================");
	}

	/**
	 * Step 3 - Using the url's obtained in step 2, collect the posts in
	 * individual thread and copy it to a seperate xls file and copy the url's
	 * of the user profiles to another text file
	 * 
	 * @param args
	 */
	public void grabThreadPosts(Map<String, String> args) {
		logger.info("=====================");
		/*
		 * // Scrape Login Map<String, String> val = new HashMap<String,
		 * String>(); val.put(PLMConstants.USER_NAME, "vin_spider_007");
		 * val.put(PLMConstants.PASSWORD, "seo@123"); login(val); // ----
		 */
		logger.info("Entring  grabThreadPosts - " + args);

		PLMBrowser browser = new DefaultBrowser();
		List<String> forumTopicURLs = null;
		PLMXlsUtils plmXlsUtils = PLMXlsUtils.getWriteThreadDataInstance();
		PLMFileUtils writeFileUtils = null;
		PLMFileUtils readFileUtils;
		try {
			if (args.get(PLMConstants.THREAD_URL_INPUT_FILE) == null
					|| "".equals(args.get(PLMConstants.THREAD_URL_INPUT_FILE))) {
				readFileUtils = new PLMFileUtils("step1.txt");
			} else {
				readFileUtils = new PLMFileUtils(
						args.get(PLMConstants.THREAD_URL_INPUT_FILE));
			}
			forumTopicURLs = readFileUtils.readFileToList();
			if (args.get(PLMConstants.USER_URL_OUTPUT_FILE) == null
					|| "".equals(args.get(PLMConstants.USER_URL_OUTPUT_FILE))) {
				writeFileUtils = new PLMFileUtils("step2.txt");
			} else {
				writeFileUtils = new PLMFileUtils(
						args.get(PLMConstants.USER_URL_OUTPUT_FILE));
			}
		} catch (IOException e1) {
			e1.printStackTrace();
		}

		int listSize = forumTopicURLs.size();
		logger.info("==================");
		logger.info("Total Numner of threads: " + listSize);
		logger.info("==================");
		for (String forumTopicURL : forumTopicURLs) {
			ParserThreadUrl parser = new ParserThreadUrl();
			List<PLMThreadPost> plmThreadPosts = new ArrayList<PLMThreadPost>();
			logger.info("URL under process " + forumTopicURL);
			String forumTopicContent = null;
			try {
				forumTopicContent = browser.execute(forumTopicURL);
			} catch (PageLoadFailedException e1) {
				e1.printStackTrace();
				logger.info(e1);
			} catch (Exception e) {
				e.printStackTrace();
				logger.info(e);
			}

			// Get the data from the page and looping until we find end of the
			// page
			while (true) {
				String nextPageUrl = null;
				// use forumTopicContent data for parsing
				// --X Logic to copy data to some external file or a buffer
				// But here we are parsing the content printing the data to
				// a
				// file
				try {
					parser.parse(forumTopicContent, plmThreadPosts);
					// check if next page is present. If present then get data
					// from
					// that page.
					nextPageUrl = parser.nextPage(forumTopicContent);
					if (null == nextPageUrl || "".equals(nextPageUrl)) {
						break;
					}
					logger.info("Nex page URL " + nextPageUrl);
					forumTopicContent = browser.execute(nextPageUrl);
				} catch (NoNextPageException e) {
					logger.info(e);
					break;
				} catch (PageLoadFailedException e) {
					e.printStackTrace();
					logger.info(e);
				} catch (Exception e) {
					e.printStackTrace();
					logger.info(e);
				}

			}
			// Write content to xls file
			for (PLMThreadPost plmThreadPost : plmThreadPosts) {
				try {
					writeFileUtils.writeToFile(plmThreadPost
							.getPostUserProfileUrl());
					plmXlsUtils.writeThreadDataToXlsFile(plmThreadPost);
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			logger.info("Threads remaining: " + (--listSize));
		}
		logger.info("grabbing posts and user profile url's Completed");
		logger.info("Exiting grabThreadPosts");
		logger.info("=====================");
	}

	/**
	 * Using the text file obtained in step 3, collect the user details and
	 * populate the xls file with he user id and his corresponding data
	 * 
	 * @param args
	 * @param textPane2
	 * @param textPane1
	 */
	public void grabUserData(Map<String, String> args) {
		logger.info("=====================");
		logger.info("Entring grabUserData - " + args);
		// Scrape Login

		/*
		 * Map<String, String> val = new HashMap<String, String>();
		 * val.put(PLMConstants.USER_NAME, "ubresearch.sv@gmail.com");
		 * val.put(PLMConstants.PASSWORD, "punnakku"); login(val);
		 */

		// ----
		String fileName = null;
		if (args.get(PLMConstants.USER_DATA_URL_INPUT_FILE) == null
				|| "".equals(args.get(PLMConstants.USER_DATA_URL_INPUT_FILE))) {
			fileName = "step2.txt";
		} else {
			fileName = args.get(PLMConstants.USER_DATA_URL_INPUT_FILE);
		}
		PLMBrowser browser = new DefaultBrowser();
		List<PLMUser> plmUsersList = new ArrayList<PLMUser>();
		Set<String> uniquePLMUsersList = null;
		PLMXlsUtils plmXlsUtils = PLMXlsUtils.getWriteUserDataInstance();
		PLMXlsUtils plmXlsUtilsWriteConditionData = PLMXlsUtils
				.getWriteUserConditionsDataInstance();
		PLMFileUtils readFileUtils = null;
		try {
			readFileUtils = new PLMFileUtils(fileName);
			uniquePLMUsersList = readFileUtils.readFileToSet();
		} catch (IOException e) {
			e.printStackTrace();
			logger.info(e);
		} catch (Exception e) {
			e.printStackTrace();
			logger.info(e);
		}

		int listSize = uniquePLMUsersList.size();
		logger.info("=====================");
		logger.info("Total Numner of User Profiles : " + listSize);
		logger.info("=====================");
		for (String plmUsersUrl : uniquePLMUsersList) {
			PLMUser plmUser = new PLMUser();
			ParserUserProfilePage parser = new ParserUserProfilePage();
			String userPageContent = null;
			try {
				userPageContent = browser.execute(plmUsersUrl);
			} catch (PageLoadFailedException e1) {
				e1.printStackTrace();
				logger.info(e1);
			} catch (Exception e) {
				e.printStackTrace();
				logger.info(e);
			}
			plmUser = parser.parse(userPageContent);
			if (null != plmUser) {
				plmUsersList.add(plmUser);
				try {
					plmXlsUtils.writeUserDataToXlsFile(plmUser);
					for (PLMUserCondition condition : plmUser.getConditions()) {
						plmXlsUtilsWriteConditionData
								.writeUserConditionsToXlsFile(condition);
					}
				} catch (IOException e) {
					e.printStackTrace();
					logger.info(e);
				} catch (Exception e) {
					e.printStackTrace();
					logger.info(e);
				}
			}
			logger.info("User Profiles remaining: " + (--listSize));
		}
		logger.info("Grabing user data Completed");
		logger.info("Exiting grabUserData");
		logger.info("=====================");
	}
}
